<?php

declare(strict_types=1);

namespace App\Fastapp\Job;

use App\Fastapp\Api\Service\Account\WalletService;
use App\Fastapp\Api\Service\Crypto\Coin\Ton;
use App\Fastapp\Model\AccountWalletAddress;
use App\Fastapp\Model\AccountWalletAddressLog;
use App\Fastapp\Model\AccountWalletAddressToken;
use App\Fastapp\Model\AccountWalletLog;
use Hyperf\AsyncQueue\Job;

class WalletAddressTransactionJob extends Job
{
    /**
     * @param int $log_id
     */
    public function __construct(public int $log_id)
    {
    }

    public function handle(): void
    {
        self::updateLog(AccountWalletAddressLog::query()->find($this->log_id));
    }

    public static function log(array $transactions, string $symbol, string $field = 'to', ?string $symbol_token = null): void
    {
        \Hyperf\Coroutine\go(function () use ($transactions, $symbol, $field, $symbol_token) {
            $address = AccountWalletAddress::query()->where(['symbol' => $symbol])
                ->whereIn('address', array_column($transactions, $field))
                ->pluck('user_id', 'address')->toArray();
            foreach ($transactions as $item) {
                if (!isset($address[$item[$field]])) continue;
                $user_id = $address[$item[$field]];
                try {
                    $map['user_id'] = $user_id;
                    $map['symbol'] = $symbol;
                    $map['symbol_token'] = $symbol_token;
                    $map['from'] = $item['from'];
                    $map['to'] = $item['to'];
                    $map['status'] = 0;
                    if ($field == 'to') {
                        $map['type'] = AccountWalletLog::RECHARGE;
                        $map['amount'] = $item['value'];
                        $map['txid'] = $item['txid'];
                        $log = AccountWalletAddressLog::query()->create($map);
                    } else {
                        $map['type'] = AccountWalletLog::WITHDRAWAL;
                        if ($symbol != 'TON') $map['txid'] = $item['txid'];
                        $log = AccountWalletAddressLog::query()->where($map)->orderByDesc('id')->first();
                        if (!$log || $log->status) continue;
                        $log->txid = $item['txid'];
                    }
                    self::updateLog($log);
                } catch (\Throwable $throwable) {
                    $s = json_encode($item);
                    fastapp_log()->get($symbol, 'wallet')->info($s);
                    sys_notify('log' . $throwable->getMessage() . '|' . $s);
                }
            }
        });
    }

    public static function updateLog(AccountWalletAddressLog $log): void
    {
        if ($log->status) return;
        $log->status = 1;
        $map['address'] = $log->to;
        $map['symbol'] = $log->symbol;
        $map['symbol_token'] = $log->symbol_token;
        try {
            $md = AccountWalletAddressToken::query()->firstOrCreate($map);
            if ($log->save()) {
                if ($log->type == AccountWalletLog::RECHARGE) {
                    WalletService::inc([
                        'user_id' => $log->user_id,
                        'amount' => $log->amount,
                        'symbol' => $log->symbol,
                        'type' => $log->type,
                        'object_type' => AccountWalletLog::OBJ_TYPE_RECHARGE,
                        'object_id' => $log->id
                    ]);
                    $md->increment('balance', $log->amount);
                    if ($log->symbol == 'TON') {//激活钱包
                        $accountAddress = AccountWalletAddress::query()->where(['symbol' => $log->symbol, 'user_id' => $log->user_id])->first();
                        if (!$accountAddress->status) {
                            Ton::transTon($accountAddress, $accountAddress->address, '0.01');
                            $accountAddress->status = 1;
                            $accountAddress->save();
                        }
                    }
                } else {
                    $md->decrement('balance', $log->amount);
                }
            }
        } catch (\Throwable $throwable) {
            sys_notify('updateLog' . $throwable->getMessage() . '|' . $throwable->getTraceAsString());
        }
    }
}
